#!/sbin/openrc-run
# Copyright 1999-2018 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

# Enable automatic non-native program execution by the kernel.

# Defaulting to OC should be safe because it comes down to:
#  - do we trust the interp itself to not be malicious?  yes; we built it.
#  - do we trust the programs we're running?  ish; same permission as native
#    binaries apply.  so if user can do bad stuff natively, cross isn't worse.
: ${QEMU_BINFMT_FLAGS:=OC}

depend() {
	after procfs
}

start() {
	ebegin "Registering qemu-user binaries (flags: ${QEMU_BINFMT_FLAGS})"

	if [ ! -d /proc/sys/fs/binfmt_misc ] ; then
		modprobe -q binfmt_misc
	fi

	if [ ! -d /proc/sys/fs/binfmt_misc ] ; then
		eend 1 "You need support for 'misc binaries' in your kernel!"
		return
	fi

	if [ ! -f /proc/sys/fs/binfmt_misc/register ] ; then
		mount -t binfmt_misc -o nodev,noexec,nosuid \
			binfmt_misc /proc/sys/fs/binfmt_misc >/dev/null 2>&1
		eend $? || return
	fi

	# Probe the native cpu type so we don't try registering them.
	local cpu="$(uname -m)"
	case "${cpu}" in
	armv[4-9]*)
		cpu="arm"
		;;
	i386|i486|i586|i686|i86pc|BePC|x86_64)
		cpu="i386"
		;;
	m68k)
		cpu="m68k"
		;;
	mips*)
		cpu="mips"
		;;
	"Power Macintosh"|ppc|ppc64)
		cpu="ppc"
		;;
	s390*)
		cpu="s390"
		;;
	sh*)
		cpu="sh"
		;;
	sparc*)
		cpu="sparc"
		;;
	esac

	# Register the interpreter for each cpu except for the native one.
	if [ "${cpu}" != "aarch64" ] ; then
		printf '%s\n' ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "aarch64_be" ] ; then
		printf '%s\n' ':qemu-aarch64_be:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-aarch64_be:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "alpha" ] ; then
		printf '%s\n' ':qemu-alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-alpha:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "arm" ] ; then
		printf '%s\n' ':qemu-arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "arm" ] ; then
		printf '%s\n' ':qemu-armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "hexagon" ] ; then
		printf '%s\n' ':qemu-hexagon:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa4\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-hexagon:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "hppa" ] ; then
		printf '%s\n' ':qemu-hppa:M::\x7f\x45\x4c\x46\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x0f:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-hppa:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "loongarch64" ] ; then
		printf '%s\n' ':qemu-loongarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02\x01:\xff\xff\xff\xff\xff\xff\xff\xfc\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-loongarch64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "m68k" ] ; then
		printf '%s\n' ':qemu-m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "microblaze" ] ; then
		printf '%s\n' ':qemu-microblaze:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xba\xab:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-microblaze:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "microblazeel" ] ; then
		printf '%s\n' ':qemu-microblazeel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xab\xba:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-microblazeel:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x07:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0\xf0:/usr/bin/qemu-mips:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x11\x00\x00:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\x00:/usr/bin/qemu-mipsel:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xf0\xf0:/usr/bin/qemu-mipsn32:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "mips" ] ; then
		printf '%s\n' ':qemu-mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x00\x00\x00:\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xf0\xff\x00:/usr/bin/qemu-mipsn32el:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "or1k" ] ; then
		printf '%s\n' ':qemu-or1k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5c:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-or1k:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "ppc" ] ; then
		printf '%s\n' ':qemu-ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "ppc" ] ; then
		printf '%s\n' ':qemu-ppc64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "ppc" ] ; then
		printf '%s\n' ':qemu-ppc64le:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x15\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\x00:/usr/bin/qemu-ppc64le:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "riscv32" ] ; then
		printf '%s\n' ':qemu-riscv32:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-riscv32:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "riscv64" ] ; then
		printf '%s\n' ':qemu-riscv64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-riscv64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "s390" ] ; then
		printf '%s\n' ':qemu-s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-s390x:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "sh" ] ; then
		printf '%s\n' ':qemu-sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-sh4:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "sh" ] ; then
		printf '%s\n' ':qemu-sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sh4eb:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "sparc" ] ; then
		printf '%s\n' ':qemu-sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc32plus:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "sparc" ] ; then
		printf '%s\n' ':qemu-sparc32plus:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x12:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc32plus:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "sparc" ] ; then
		printf '%s\n' ':qemu-sparc64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2b:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc64:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "xtensa" ] ; then
		printf '%s\n' ':qemu-xtensa:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-xtensa:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	if [ "${cpu}" != "xtensaeb" ] ; then
		printf '%s\n' ':qemu-xtensaeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x5e:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-xtensaeb:'"${QEMU_BINFMT_FLAGS}" >/proc/sys/fs/binfmt_misc/register
	fi
	eend 0
}

stop() {
	# We unregister everything in the "qemu-xxx" namespace.
	ebegin "Unregistering qemu-user binaries"
	local f
	for f in /proc/sys/fs/binfmt_misc/qemu-* ; do
		if [ -f "${f}" ] ; then
			echo '-1' > "${f}"
		fi
	done
	eend 0
}
